/*
 * Project Name : NOBUNAGA
 * Created on 2007/04/04
 */
package jp.sengoku.oda
{
	import flash.display.Shape;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	import mx.charts.chartClasses.ChartElement;
	import mx.charts.chartClasses.PolarChart;
	import mx.events.FlexEvent;
	import mx.events.ResizeEvent;
	import flash.text.TextField;
	import mx.controls.Label;
	import flash.text.StaticText;
	import mx.charts.chartClasses.ChartBase;


	/** レーダチャート
	 * ベータ版
	 * ・以降各プロパティ実装予定
	 * @author u102379@gmail.com
	 */	
	public class UesugiChart extends ChartBase 
	{
		//チャート軸のオブジェクト
        private var chartBaseLine:Array = new Array();

		//チャート軸のテキストオブジェクト
        private var chartBaseLineText:Array = new Array();

		//チャート要素のオブジェクト
        private var chartElement:Array = new Array();

		[Bindable]
		//軸の次元数指定（デフォルト：要素の次元数）
		public var NumberOfDimension:Number = -1;

		[Bindable]
		//軸の色（デフォルト：赤）
		public var DimensionLineColor:uint = 0xFF0000;

		//チャート軸、1軸ごとの角度
		private var unitAngle:Number;

		[Bindable]
		//チャート軸の基本の長さ（チャートの大きさとの倍率を指定）（デフォルト：3/8）
		public var DimensionBarRate:Number = 3/8;

		[Bindable]
		//チャート軸の幅（デフォルト：2）
		public var DimensionLineWidth:Number = 2;

		//チャート軸の長さ
		private var dimensionBarLength:Number;
		
		[Bindable]
		//要素座標の円の半径（デフォルト：5）
		public var  ElementRadius:Number = 5;

		//中心座標
		private var rootPoint:Point;

    	/** コンストラクタでござる
		 */
		public function UesugiChart() {
			super();
			this.addEventListener(MouseEvent.CLICK, _clickHandler);

			//描画タイミングをイベントに指定
			this.addEventListener(FlexEvent.CREATION_COMPLETE, _reDrow);
			this.addEventListener(ResizeEvent.RESIZE, _reDrow);

		}

		/** 再描画イベントハンドラ
		 * 各チャートオブジェクト（描画軸、要素）の定義を再計算する。
		 * @param  event
		 * @return void
		 */
		private function _reDrow(event:Object):void{
			//設定値から、必要データの計算を行う
			createChartData();

			//すでに座標軸が描画されている場合は、削除する。
			if(chartBaseLine[0] != null && chartBaseLine[0].parent == this)
				removeChartObject();

			//チャート軸の作成
			createChartBar();

			//チャート要素の作成
			createChartElement();
		}
		

		/** データからグローバル座標を算出する
		 * ローカル座標の中心から、角度・距離を引数にして、グローバル座標を算出する。
		 * @param  ... dataValues	データ（dataValues[0]角度,dataValues[1]放射軸）
		 * @return Point			グローバル座標
		 */
		public function dataToGlobal(... dataValues):Point{
			var localPoint:Point = new Point(dataValues[0],dataValues[1])
			localPoint.x = Math.sin(dataValues[0]) * dataValues[1] + width/2;
			localPoint.y = - Math.cos(dataValues[0]) * dataValues[1] + height/2;
			return localPoint;
		}

		/** ランダムに色情報を取得する（引数と紐付ける）
		 * @param  n	色情報を選択するための数値(整数)
		 * @return uint	色情報
		 */
		private function getRandomColor(n:Number):uint{
			
			var elementColors:Array = new Array();
			elementColors.push(0x00FF00);
			elementColors.push(0x0000FF);
			elementColors.push(0xFFFF00);
			elementColors.push(0xFF00FF);
			elementColors.push(0x00FFFF);
			
			var m:Number = n % elementColors.length;
			
			return elementColors[m];
		}

		
		/** チャートオブジェクトの削除を行う。
		 * @return void
		 */
		private function removeChartObject():void{
			//チャート軸オブジェクトの削除
			for(var i:Number=0; i<chartBaseLine.length; i++){
				this.removeChild(chartBaseLine[i]);
				chartBaseLine[i] = null;
			}
			chartBaseLine = null;
			chartBaseLine = new Array();

			//チャート軸テキストオブジェクトの削除
			for(i=0; i<chartBaseLineText.length; i++){
				this.removeChild(chartBaseLineText[i]);
				chartBaseLineText[i] = null;
			}
			chartBaseLineText = null;
			chartBaseLineText = new Array();

			//チャート要素オブジェクトの削除
			for(i=0; i<chartElement.length; i++){
				this.removeChild(chartElement[i]);
				chartElement[i] = null;
			}
			chartElement = null;
			chartElement = new Array();
		}
		
		override public function set series(value:Array):void {
			trace(value);
			super.series = value;
		}
		
		/** 設定値（プロパティ等）からチャートデータの計算を行う
		 * @return void
		 */
		private function createChartData():void{
			//チャートの次元数（軸の数）の設定
			if(NumberOfDimension < 0 || series.length < NumberOfDimension )
				NumberOfDimension = series.length;
			
			//チャート軸、1軸ごとの角度の計算
			unitAngle = 2*Math.PI/NumberOfDimension;
			
			//中心座標
			rootPoint = dataToGlobal(0,0);
			
			//チャート軸の長さ（デフォルト：チャートの大きさ*3/8）
			if(dataRegion.width < dataRegion.height)
				dimensionBarLength = dataRegion.width*DimensionBarRate;
			else
				dimensionBarLength = dataRegion.height*DimensionBarRate;
		}

		/** チャート軸の作成
		 * @return void
		 */ 		
		private function createChartBar():void{
			var points:Point;
			for(var i:Number=0;i<NumberOfDimension;i++){
				//軸の作成
				chartBaseLine.push(new Shape);
				points = dataToGlobal(unitAngle*i, dimensionBarLength);
				chartBaseLine[i].graphics.lineStyle(DimensionLineWidth,DimensionLineColor,1);
				chartBaseLine[i].graphics.moveTo(rootPoint.x, rootPoint.y);
				chartBaseLine[i].graphics.lineTo(points.x, points.y);
				addChild(chartBaseLine[i]);
				
				//ラベルの作成
				chartBaseLineText.push(new Label);
				var lab:Label = new Label();
				chartBaseLineText[i].text = series[i].displayName;
				points = dataToGlobal(unitAngle*i, dimensionBarLength+20);
				chartBaseLineText[i].validateNow();
				chartBaseLineText[i].x = points.x;
				chartBaseLineText[i].y = points.y;


				chartBaseLineText[i].width = chartBaseLineText[i].text.length * chartBaseLineText[i].getStyle("fontSize");
				chartBaseLineText[i].height = chartBaseLineText[i].textHeight + 5;
//var stringStyle:String = new String();
//lab.getExplicitOrMeasuredWidth()
//chartBaseLineText[i].setStyle("fontSize",50);

				addChild(chartBaseLineText[i]);
			}
		}
		
		/** チャート要素の作成
		 * @return void
		 */ 		
		private function createChartElement():void{
			var points:Point;
			var field:String;
			
			for(var i:Number=0; i< dataProvider.length; i++){
				chartElement.push(new Shape);
				//チャート要素のラインスタイルを設定する
				chartElement[i].graphics.lineStyle(3,getRandomColor(i),1);
				for(var j:Number=0; j< NumberOfDimension; j++){
					//軸上の座標を取得
					points = getDataPoint(i, j);
					//線を引く
					if(j!=0){
						chartElement[i].graphics.lineTo(points.x, points.y);
					}
					
					chartElement[i].graphics.beginFill(getRandomColor(i), 1);
					chartElement[i].graphics.drawCircle(points.x,points.y,ElementRadius);
					chartElement[i].graphics.moveTo(points.x, points.y);
				}
				points = getDataPoint(i, 0);
				chartElement[i].graphics.lineTo(points.x, points.y);
				this.addChild(chartElement[i]);
			}
		}
		
		/** 指定されたデータのグローバル座標を返す
		 * 
		 * @param dataProviderIndex	データプロバイダの対象インデックス
		 * @param elementIndex		要素の対象インデックス
		 */		 
		private function getDataPoint(dataProviderIndex:Number, elementIndex:Number):Point{
			//要素名
			var elementName:String = series[elementIndex].yField;
			//軸の最大数値
			var elementBarMaxValue:Number = Number(series[elementIndex].maxHeight);
			//要素データ
			var dataValue:Number = Number(dataProvider[dataProviderIndex][elementName]);
			
			if(dataProvider[dataProviderIndex].hasOwnProperty(elementName)==true){
				return dataToGlobal(unitAngle*elementIndex, dimensionBarLength*dataValue/elementBarMaxValue );
			}else{
				return dataToGlobal(0, 0);
			}
		}
		
		/** マウスクリックイベントハンドラ
		 * クリックされたオブジェクトを最前面に移動する
		 * @param  event
		 */
		private function _clickHandler(event:MouseEvent):void{
			//ヒットしたオブジェクトを最前面へ
			for(var i:Number = 0; i < chartElement.length; i++){
				if(chartElement[i].hitTestPoint(event.stageX, event.stageY, true) == true){
					removeChild(chartElement[i]);
					addChild(chartElement[i]);
					i = chartElement.length;
				}

			}
			trace(" :",dataProvider[0]["Country"],chartElement[0].hitTestPoint(event.stageX, event.stageY, true)," :",dataProvider[1]["Country"],	chartElement[1].hitTestPoint(event.stageX, event.stageY, true)," :",dataProvider[2]["Country"],	chartElement[2].hitTestPoint(event.stageX, event.stageY, true)," :X",event.localX," :Y", event.stageX);
		}
		
	}
}
